feat: add reusable modal system with theme support and view registry#6
Merged
Conversation
Add MagicStarterModalTheme (13 className tokens), MagicStarterDialogShell (internal composition widget), MagicStarterConfirmDialog with ConfirmDialogVariant enum (primary/danger/warning), and modal view registry (registerModal/hasModal/ makeModal with 3 auto-registered defaults). Refactor PasswordConfirmDialog and TwoFactorModal to read theme tokens at build time. Replace Material AlertDialog in team settings with ConfirmDialog. 555 tests passing.
There was a problem hiding this comment.
Pull request overview
Adds a reusable modal/dialog system to magic_starter with centralized theme tokens and a modal registry, then migrates existing dialogs and team settings confirms onto the new primitives.
Changes:
- Introduces
MagicStarterModalTheme+MagicStarter.useModalTheme()to control dialog styling via Wind UI className tokens. - Adds
MagicStarterDialogShell(internal) andMagicStarterConfirmDialog(exported) withConfirmDialogVariant. - Extends
MagicStarterViewRegistryto register/build modals and auto-registers default modal keys; refactors existing dialogs and replaces team settingsAlertDialog.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/src/magic_starter_manager.dart | Adds modal theme storage/reset + default modal registrations. |
| lib/src/facades/magic_starter.dart | Exposes useModalTheme() + modalTheme getter. |
| lib/src/ui/magic_starter_view_registry.dart | Adds modal builder map + registerModal/hasModal/makeModal. |
| lib/src/ui/widgets/magic_starter_dialog_shell.dart | New internal dialog shell composing Wind UI tokens. |
| lib/src/ui/widgets/magic_starter_confirm_dialog.dart | New reusable confirm dialog built on the shell + variants. |
| lib/src/ui/widgets/magic_starter_password_confirm_dialog.dart | Refactors styling to consume modalTheme tokens. |
| lib/src/ui/widgets/magic_starter_two_factor_modal.dart | Refactors styling/maxWidth to consume modalTheme tokens. |
| lib/src/ui/views/teams/magic_starter_team_settings_view.dart | Replaces Material AlertDialog confirms with MagicStarterConfirmDialog. |
| lib/magic_starter.dart | Exports MagicStarterConfirmDialog from the barrel. |
| test/facades/magic_starter_facade_test.dart | Adds coverage for modal theme defaults/override/reset + default modal keys. |
| test/ui/magic_starter_view_registry_test.dart | Adds tests for modal registry operations and clear behavior. |
| test/ui/widgets/magic_starter_dialog_shell_test.dart | New widget tests for shell rendering + theme token reads. |
| test/ui/widgets/magic_starter_confirm_dialog_test.dart | New widget tests for confirm dialog behavior/variants/show(). |
| test/ui/widgets/magic_starter_password_confirm_dialog_test.dart | Adds modal-theme integration assertions. |
| test/ui/widgets/magic_starter_two_factor_modal_test.dart | Adds modal-theme integration assertion. |
| test/ui/views/teams/magic_starter_team_settings_view_test.dart | New widget tests asserting confirm dialog usage (no AlertDialog). |
| doc/basics/views-and-layouts.md | Documents MagicStarterConfirmDialog usage and parameters. |
| doc/architecture/view-registry.md | Documents modal registry API + default modal keys. |
| doc/architecture/manager.md | Documents modal theme API and configuration. |
| README.md | Updates theming docs (navigation + modal theme) and widget list. |
| CHANGELOG.md | Records new modal theme/dialog/registry features. |
| CLAUDE.md | Adds “gotchas” around modal theme ordering and className sourcing. |
| .claude/rules/widgets.md | Adds dialog/variant/theme consumption rules for widgets. |
Comments suppressed due to low confidence (2)
doc/architecture/view-registry.md:44
- Docs:
_modalsis shown asMap<String, MagicStarterViewBuilder>, but the implementation uses a dedicatedMagicStarterModalBuildertypedef. Update the snippet and add thetypedef MagicStarterModalBuilder = Widget Function();so the docs match the code.
The registry maintains three internal maps — one for view builders, one for layout builders, and one for modal builders:
```dart
final Map<String, MagicStarterViewBuilder> _builders = {};
final Map<String, MagicStarterLayoutBuilder> _layouts = {};
final Map<String, MagicStarterViewBuilder> _modals = {};
The builder typedefs:
typedef MagicStarterViewBuilder = Widget Function();
typedef MagicStarterLayoutBuilder = Widget Function(Widget child);**doc/architecture/view-registry.md:101**
* Docs: The section says "Both methods throw StateError" but there are now three builders (`make`, `makeLayout`, `makeModal`). Update this wording to reflect that all the `make*` methods throw `StateError` when a key is missing.
Building Widgets
Widget make(String key)
Widget makeLayout(String key, {required Widget child})
Widget makeModal(String key)Both methods throw StateError when the requested key is not registered:
throw StateError('No view builder registered for key "$key".');[!NOTE]
AStateErrorfrommake()ormakeLayout()usually means a feature flag is disabled. Feature-gated views (teams, two-factor, notifications) are only registered when their correspondingMagicStarterConfig.has*Features()flag returnstrue.
</details>
---
💡 <a href="/fluttersdk/magic_starter/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
…itle
- Add try/catch to ConfirmDialog._onConfirm() to prevent stuck loading state
- Use trans('common.confirm') as default modal.confirm title instead of empty string
- Fix view-registry.md: MagicStarterModalBuilder typedef, "All three methods"
- Fix manager.md: maxWidth default is 448.0, not null
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
MagicStarterModalTheme— 13 Wind UI className token fields for customizable dialog styling viaMagicStarter.useModalTheme()MagicStarterConfirmDialogwithConfirmDialogVariantenum (primary/danger/warning) and internalMagicStarterDialogShellcomposition widgetViewRegistrywithregisterModal()/hasModal()/makeModal()+ 3 auto-registered default modalsPasswordConfirmDialogandTwoFactorModalto read theme tokens at build time (no breaking changes)AlertDialogin team settings withMagicStarterConfirmDialogTest plan
flutter test --coverage)flutter analyze --no-fatal-infos— clean (1 pre-existing info)dart format --set-exit-if-changed .— 0 changes